`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date:    20:57:52 11/11/2011 
// Design Name: 
// Module Name:    matrix_mul 
// Project Name: 
// Target Devices: 
// Tool versions: 
// Description: 
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//
//////////////////////////////////////////////////////////////////////////////////
module matrix_mul(
    input[2047:0]  din_row,
    input[2047:0]  din_col,
    input          clk,
    input          rst,
    output         busy,
    output         cwen,
    output[5:0]    iaddr_row,
    output[5:0]    iaddr_col,
    output[5:0]    oaddr,
    output[2047:0] dout
    );

wire[2047:0] write_row;
wire[2047:0] read_col;
wire[31:0]   row_masked;

reg[2047:0] write_buff;
reg[5:0]    addr_select;
reg[12:0]   cal_cnt;
reg         is_calculating;
reg         cwen_local;
reg         wait_for_input;

// input binding
assign read_col = din_col;

// output binding
assign dout = write_buff;
assign iaddr_row = cal_cnt[11:6];
assign iaddr_col = cal_cnt[5:0];
assign oaddr = addr_select;
assign busy = is_calculating;
assign cwen = cwen_local;

// databus masker
masker_2048to32 masker(.din(din_row), .index(cal_cnt[5:0]), .dout(row_masked));

always @(negedge clk) begin
    if(rst) begin
        cal_cnt <= 0;
        addr_select <= 0;
    end
    else if(~wait_for_input & is_calculating) begin
        cal_cnt <= cal_cnt + 1;
        addr_select <= cal_cnt[11:6];
    end
end

always @(posedge clk) begin
    if(rst) begin
        //cal_cnt <= 0;
        //cal_cnt = 13'b1111111111111;
        write_buff <= 0;
        //addr_select <= 0;
        is_calculating <= 1;
        cwen_local <= 0;
        wait_for_input <= 1;
    end
    else if(wait_for_input) begin
        wait_for_input <= 0;
    end
    else if(is_calculating) begin
        //cal_cnt <= cal_cnt + 1;
        //addr_select <= cal_cnt[11:6];
        cwen_local <= addr_select[0] ^ cal_cnt[6];
        is_calculating <= ~cal_cnt[12];
    end
    else begin
        cwen_local <= 0;
    end
        if(|cal_cnt[5:0] == 0)
            write_buff <= 0;
        else begin
            write_buff[  31:   0] <= write_buff[  31:   0] + write_row[  31:   0];
            write_buff[  63:  32] <= write_buff[  63:  32] + write_row[  63:  32];
            write_buff[  95:  64] <= write_buff[  95:  64] + write_row[  95:  64];
            write_buff[ 127:  96] <= write_buff[ 127:  96] + write_row[ 127:  96];
            write_buff[ 159: 128] <= write_buff[ 159: 128] + write_row[ 159: 128];
            write_buff[ 191: 160] <= write_buff[ 191: 160] + write_row[ 191: 160];
            write_buff[ 223: 192] <= write_buff[ 223: 192] + write_row[ 223: 192];
            write_buff[ 255: 224] <= write_buff[ 255: 224] + write_row[ 255: 224];
            write_buff[ 287: 256] <= write_buff[ 287: 256] + write_row[ 287: 256];
            write_buff[ 319: 288] <= write_buff[ 319: 288] + write_row[ 319: 288];
            write_buff[ 351: 320] <= write_buff[ 351: 320] + write_row[ 351: 320];
            write_buff[ 383: 352] <= write_buff[ 383: 352] + write_row[ 383: 352];
            write_buff[ 415: 384] <= write_buff[ 415: 384] + write_row[ 415: 384];
            write_buff[ 447: 416] <= write_buff[ 447: 416] + write_row[ 447: 416];
            write_buff[ 479: 448] <= write_buff[ 479: 448] + write_row[ 479: 448];
            write_buff[ 511: 480] <= write_buff[ 511: 480] + write_row[ 511: 480];
            write_buff[ 543: 512] <= write_buff[ 543: 512] + write_row[ 543: 512];
            write_buff[ 575: 544] <= write_buff[ 575: 544] + write_row[ 575: 544];
            write_buff[ 607: 576] <= write_buff[ 607: 576] + write_row[ 607: 576];
            write_buff[ 639: 608] <= write_buff[ 639: 608] + write_row[ 639: 608];
            write_buff[ 671: 640] <= write_buff[ 671: 640] + write_row[ 671: 640];
            write_buff[ 703: 672] <= write_buff[ 703: 672] + write_row[ 703: 672];
            write_buff[ 735: 704] <= write_buff[ 735: 704] + write_row[ 735: 704];
            write_buff[ 767: 736] <= write_buff[ 767: 736] + write_row[ 767: 736];
            write_buff[ 799: 768] <= write_buff[ 799: 768] + write_row[ 799: 768];
            write_buff[ 831: 800] <= write_buff[ 831: 800] + write_row[ 831: 800];
            write_buff[ 863: 832] <= write_buff[ 863: 832] + write_row[ 863: 832];
            write_buff[ 895: 864] <= write_buff[ 895: 864] + write_row[ 895: 864];
            write_buff[ 927: 896] <= write_buff[ 927: 896] + write_row[ 927: 896];
            write_buff[ 959: 928] <= write_buff[ 959: 928] + write_row[ 959: 928];
            write_buff[ 991: 960] <= write_buff[ 991: 960] + write_row[ 991: 960];
            write_buff[1023: 992] <= write_buff[1023: 992] + write_row[1023: 992];
            write_buff[1055:1024] <= write_buff[1055:1024] + write_row[1055:1024];
            write_buff[1087:1056] <= write_buff[1087:1056] + write_row[1087:1056];
            write_buff[1119:1088] <= write_buff[1119:1088] + write_row[1119:1088];
            write_buff[1151:1120] <= write_buff[1151:1120] + write_row[1151:1120];
            write_buff[1183:1152] <= write_buff[1183:1152] + write_row[1183:1152];
            write_buff[1215:1184] <= write_buff[1215:1184] + write_row[1215:1184];
            write_buff[1247:1216] <= write_buff[1247:1216] + write_row[1247:1216];
            write_buff[1279:1248] <= write_buff[1279:1248] + write_row[1279:1248];
            write_buff[1311:1280] <= write_buff[1311:1280] + write_row[1311:1280];
            write_buff[1343:1312] <= write_buff[1343:1312] + write_row[1343:1312];
            write_buff[1375:1344] <= write_buff[1375:1344] + write_row[1375:1344];
            write_buff[1407:1376] <= write_buff[1407:1376] + write_row[1407:1376];
            write_buff[1439:1408] <= write_buff[1439:1408] + write_row[1439:1408];
            write_buff[1471:1440] <= write_buff[1471:1440] + write_row[1471:1440];
            write_buff[1503:1472] <= write_buff[1503:1472] + write_row[1503:1472];
            write_buff[1535:1504] <= write_buff[1535:1504] + write_row[1535:1504];
            write_buff[1567:1536] <= write_buff[1567:1536] + write_row[1567:1536];
            write_buff[1599:1568] <= write_buff[1599:1568] + write_row[1599:1568];
            write_buff[1631:1600] <= write_buff[1631:1600] + write_row[1631:1600];
            write_buff[1663:1632] <= write_buff[1663:1632] + write_row[1663:1632];
            write_buff[1695:1664] <= write_buff[1695:1664] + write_row[1695:1664];
            write_buff[1727:1696] <= write_buff[1727:1696] + write_row[1727:1696];
            write_buff[1759:1728] <= write_buff[1759:1728] + write_row[1759:1728];
            write_buff[1791:1760] <= write_buff[1791:1760] + write_row[1791:1760];
            write_buff[1823:1792] <= write_buff[1823:1792] + write_row[1823:1792];
            write_buff[1855:1824] <= write_buff[1855:1824] + write_row[1855:1824];
            write_buff[1887:1856] <= write_buff[1887:1856] + write_row[1887:1856];
            write_buff[1919:1888] <= write_buff[1919:1888] + write_row[1919:1888];
            write_buff[1951:1920] <= write_buff[1951:1920] + write_row[1951:1920];
            write_buff[1983:1952] <= write_buff[1983:1952] + write_row[1983:1952];
            write_buff[2015:1984] <= write_buff[2015:1984] + write_row[2015:1984];
            write_buff[2047:2016] <= write_buff[2047:2016] + write_row[2047:2016];
        end
    //end
end

cal_unit cunit_00(.din_row(row_masked), .din_col(read_col[  31:   0]), .clk(clk), .dout(write_row[  31:   0]));
cal_unit cunit_01(.din_row(row_masked), .din_col(read_col[  63:  32]), .clk(clk), .dout(write_row[  63:  32]));
cal_unit cunit_02(.din_row(row_masked), .din_col(read_col[  95:  64]), .clk(clk), .dout(write_row[  95:  64]));
cal_unit cunit_03(.din_row(row_masked), .din_col(read_col[ 127:  96]), .clk(clk), .dout(write_row[ 127:  96]));
cal_unit cunit_04(.din_row(row_masked), .din_col(read_col[ 159: 128]), .clk(clk), .dout(write_row[ 159: 128]));
cal_unit cunit_05(.din_row(row_masked), .din_col(read_col[ 191: 160]), .clk(clk), .dout(write_row[ 191: 160]));
cal_unit cunit_06(.din_row(row_masked), .din_col(read_col[ 223: 192]), .clk(clk), .dout(write_row[ 223: 192]));
cal_unit cunit_07(.din_row(row_masked), .din_col(read_col[ 255: 224]), .clk(clk), .dout(write_row[ 255: 224]));
cal_unit cunit_08(.din_row(row_masked), .din_col(read_col[ 287: 256]), .clk(clk), .dout(write_row[ 287: 256]));
cal_unit cunit_09(.din_row(row_masked), .din_col(read_col[ 319: 288]), .clk(clk), .dout(write_row[ 319: 288]));
cal_unit cunit_10(.din_row(row_masked), .din_col(read_col[ 351: 320]), .clk(clk), .dout(write_row[ 351: 320]));
cal_unit cunit_11(.din_row(row_masked), .din_col(read_col[ 383: 352]), .clk(clk), .dout(write_row[ 383: 352]));
cal_unit cunit_12(.din_row(row_masked), .din_col(read_col[ 415: 384]), .clk(clk), .dout(write_row[ 415: 384]));
cal_unit cunit_13(.din_row(row_masked), .din_col(read_col[ 447: 416]), .clk(clk), .dout(write_row[ 447: 416]));
cal_unit cunit_14(.din_row(row_masked), .din_col(read_col[ 479: 448]), .clk(clk), .dout(write_row[ 479: 448]));
cal_unit cunit_15(.din_row(row_masked), .din_col(read_col[ 511: 480]), .clk(clk), .dout(write_row[ 511: 480]));
cal_unit cunit_16(.din_row(row_masked), .din_col(read_col[ 543: 512]), .clk(clk), .dout(write_row[ 543: 512]));
cal_unit cunit_17(.din_row(row_masked), .din_col(read_col[ 575: 544]), .clk(clk), .dout(write_row[ 575: 544]));
cal_unit cunit_18(.din_row(row_masked), .din_col(read_col[ 607: 576]), .clk(clk), .dout(write_row[ 607: 576]));
cal_unit cunit_19(.din_row(row_masked), .din_col(read_col[ 639: 608]), .clk(clk), .dout(write_row[ 639: 608]));
cal_unit cunit_20(.din_row(row_masked), .din_col(read_col[ 671: 640]), .clk(clk), .dout(write_row[ 671: 640]));
cal_unit cunit_21(.din_row(row_masked), .din_col(read_col[ 703: 672]), .clk(clk), .dout(write_row[ 703: 672]));
cal_unit cunit_22(.din_row(row_masked), .din_col(read_col[ 735: 704]), .clk(clk), .dout(write_row[ 735: 704]));
cal_unit cunit_23(.din_row(row_masked), .din_col(read_col[ 767: 736]), .clk(clk), .dout(write_row[ 767: 736]));
cal_unit cunit_24(.din_row(row_masked), .din_col(read_col[ 799: 768]), .clk(clk), .dout(write_row[ 799: 768]));
cal_unit cunit_25(.din_row(row_masked), .din_col(read_col[ 831: 800]), .clk(clk), .dout(write_row[ 831: 800]));
cal_unit cunit_26(.din_row(row_masked), .din_col(read_col[ 863: 832]), .clk(clk), .dout(write_row[ 863: 832]));
cal_unit cunit_27(.din_row(row_masked), .din_col(read_col[ 895: 864]), .clk(clk), .dout(write_row[ 895: 864]));
cal_unit cunit_28(.din_row(row_masked), .din_col(read_col[ 927: 896]), .clk(clk), .dout(write_row[ 927: 896]));
cal_unit cunit_29(.din_row(row_masked), .din_col(read_col[ 959: 928]), .clk(clk), .dout(write_row[ 959: 928]));
cal_unit cunit_30(.din_row(row_masked), .din_col(read_col[ 991: 960]), .clk(clk), .dout(write_row[ 991: 960]));
cal_unit cunit_31(.din_row(row_masked), .din_col(read_col[1023: 992]), .clk(clk), .dout(write_row[1023: 992]));
cal_unit cunit_32(.din_row(row_masked), .din_col(read_col[1055:1024]), .clk(clk), .dout(write_row[1055:1024]));
cal_unit cunit_33(.din_row(row_masked), .din_col(read_col[1087:1056]), .clk(clk), .dout(write_row[1087:1056]));
cal_unit cunit_34(.din_row(row_masked), .din_col(read_col[1119:1088]), .clk(clk), .dout(write_row[1119:1088]));
cal_unit cunit_35(.din_row(row_masked), .din_col(read_col[1151:1120]), .clk(clk), .dout(write_row[1151:1120]));
cal_unit cunit_36(.din_row(row_masked), .din_col(read_col[1183:1152]), .clk(clk), .dout(write_row[1183:1152]));
cal_unit cunit_37(.din_row(row_masked), .din_col(read_col[1215:1184]), .clk(clk), .dout(write_row[1215:1184]));
cal_unit cunit_38(.din_row(row_masked), .din_col(read_col[1247:1216]), .clk(clk), .dout(write_row[1247:1216]));
cal_unit cunit_39(.din_row(row_masked), .din_col(read_col[1279:1248]), .clk(clk), .dout(write_row[1279:1248]));
cal_unit cunit_40(.din_row(row_masked), .din_col(read_col[1311:1280]), .clk(clk), .dout(write_row[1311:1280]));
cal_unit cunit_41(.din_row(row_masked), .din_col(read_col[1343:1312]), .clk(clk), .dout(write_row[1343:1312]));
cal_unit cunit_42(.din_row(row_masked), .din_col(read_col[1375:1344]), .clk(clk), .dout(write_row[1375:1344]));
cal_unit cunit_43(.din_row(row_masked), .din_col(read_col[1407:1376]), .clk(clk), .dout(write_row[1407:1376]));
cal_unit cunit_44(.din_row(row_masked), .din_col(read_col[1439:1408]), .clk(clk), .dout(write_row[1439:1408]));
cal_unit cunit_45(.din_row(row_masked), .din_col(read_col[1471:1440]), .clk(clk), .dout(write_row[1471:1440]));
cal_unit cunit_46(.din_row(row_masked), .din_col(read_col[1503:1472]), .clk(clk), .dout(write_row[1503:1472]));
cal_unit cunit_47(.din_row(row_masked), .din_col(read_col[1535:1504]), .clk(clk), .dout(write_row[1535:1504]));
cal_unit cunit_48(.din_row(row_masked), .din_col(read_col[1567:1536]), .clk(clk), .dout(write_row[1567:1536]));
cal_unit cunit_49(.din_row(row_masked), .din_col(read_col[1599:1568]), .clk(clk), .dout(write_row[1599:1568]));
cal_unit cunit_50(.din_row(row_masked), .din_col(read_col[1631:1600]), .clk(clk), .dout(write_row[1631:1600]));
cal_unit cunit_51(.din_row(row_masked), .din_col(read_col[1663:1632]), .clk(clk), .dout(write_row[1663:1632]));
cal_unit cunit_52(.din_row(row_masked), .din_col(read_col[1695:1664]), .clk(clk), .dout(write_row[1695:1664]));
cal_unit cunit_53(.din_row(row_masked), .din_col(read_col[1727:1696]), .clk(clk), .dout(write_row[1727:1696]));
cal_unit cunit_54(.din_row(row_masked), .din_col(read_col[1759:1728]), .clk(clk), .dout(write_row[1759:1728]));
cal_unit cunit_55(.din_row(row_masked), .din_col(read_col[1791:1760]), .clk(clk), .dout(write_row[1791:1760]));
cal_unit cunit_56(.din_row(row_masked), .din_col(read_col[1823:1792]), .clk(clk), .dout(write_row[1823:1792]));
cal_unit cunit_57(.din_row(row_masked), .din_col(read_col[1855:1824]), .clk(clk), .dout(write_row[1855:1824]));
cal_unit cunit_58(.din_row(row_masked), .din_col(read_col[1887:1856]), .clk(clk), .dout(write_row[1887:1856]));
cal_unit cunit_59(.din_row(row_masked), .din_col(read_col[1919:1888]), .clk(clk), .dout(write_row[1919:1888]));
cal_unit cunit_60(.din_row(row_masked), .din_col(read_col[1951:1920]), .clk(clk), .dout(write_row[1951:1920]));
cal_unit cunit_61(.din_row(row_masked), .din_col(read_col[1983:1952]), .clk(clk), .dout(write_row[1983:1952]));
cal_unit cunit_62(.din_row(row_masked), .din_col(read_col[2015:1984]), .clk(clk), .dout(write_row[2015:1984]));
cal_unit cunit_63(.din_row(row_masked), .din_col(read_col[2047:2016]), .clk(clk), .dout(write_row[2047:2016]));


endmodule
